﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Common;

namespace NextNet
{
    public class NextClient : HandleFile
    {
        public int ChonglianTimeOut = 30000;

        Socket ClientSocket;
        Thread ThreadReceiver;
        Thread ThreadSender;
        Thread ThreadHeart;
        
        public int ClientID = 0;
        string ServerIP;
        int ServerProt;

        public delegate void DisposeEventHandle(object sender, DataDisp e);
        public event DisposeEventHandle DisoposeHandle;

        public List<byte[]> ListMessage = new List<byte[]>();

        bool Running
        {
            get
            {
                return (ClientSocket != null || ThreadReceiver != null || ThreadSender != null);
            }
        }

        public void Start(string ip, int prot)
        {
            if (Running)
            {
                Logfile log = new Logfile(0);
                log.Write("客户端已运行", "Start");
                Environment.Exit(0);
            }

            ServerIP = ip;
            ServerProt = prot;

            End:
            try
            {
                IPAddress ipAddress = IPAddress.Parse(ServerIP);
                IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, ServerProt);

                ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                ClientSocket.Connect(ipEndPoint);

            }
            catch (Exception ex)
            {
                Logfile log = new Logfile(0);
                log.Write(ex.Message, "Connect");

                if (ClientSocket != null)
                    ClientSocket.Close();

                Thread.Sleep(ChonglianTimeOut);

                goto End;
            }

            ThreadReceiver = new Thread(ClientReceiver);
            ThreadReceiver.Start();

            SendHandle += SendMessage;
            
            ThreadSender = new Thread(ClientSender);
            ThreadSender.Start();
            

            //ThreadHeart = new Thread(SendHeart);
            //ThreadHeart.Start();
        }

        private void SendMessage(SendMessage mess)
        {
            lock(ListMessage)
            {
                ListMessage.Add(mess.Stream);
            }
        }

        void ClientReceiver()
        {

            while (true)
            {
                int streamLength = 0;

                byte[] head = new byte[StreamHead.HeadLength];
                byte[] temp = new byte[1024];
                byte[] stream;

                try
                {
                    int sub = StreamHead.HeadLength;
                    int length;

                    while (true)
                    {
                        int len = (temp.Length < sub) ? temp.Length : sub;
                        length = ClientSocket.Receive(temp, len, SocketFlags.None);

                        if (length <= 0) goto End;//重新接收
                        if (length == sub)
                        {
                            Array.Copy(temp, 0, head, head.Length - sub, length);
                            break;
                        }
                        else
                        {
                            Array.Copy(temp, 0, head, head.Length - sub, length);
                            sub -= length;
                        }
                    }
                    StreamHead.Read(head, out streamLength, out int clientID, out DataType dataType, out MessType messType);

                    if (streamLength > 0)
                    {
                        stream = new byte[streamLength];
                        sub = streamLength;
                        while (true)
                        {
                            int len = (temp.Length < sub) ? temp.Length : sub;
                            length = ClientSocket.Receive(temp, len, SocketFlags.None);

                            if (length <= 0) goto End;

                            if (length == sub)
                            {
                                Array.Copy(temp, 0, stream, stream.Length - sub, length);
                                break;
                            }
                            else
                            {
                                Array.Copy(temp, 0, stream, stream.Length - sub, length);
                                sub -= length;
                            }
                        }

                    }
                    else
                    {
                        stream = head;
                    }

                    //处理消息
                    DisoposeHandle?.Invoke(this, new DataDisp()
                    {
                        ID = clientID,
                        Data = dataType,
                        Type = messType,
                        Stream = stream
                    });
                }
                catch (Exception ex)
                {
                    Logfile log = new Logfile(0);
                    log.Write(ex.Message, "ClientReceiver");
                    Thread.Sleep(ChonglianTimeOut);
                    goto End;
                }

            }
            End:
            new Thread(Stop).Start();
        }

        void Stop()
        {
            if (ClientSocket != null)
            {
                ClientSocket.Close();
                ClientSocket = null;
            }
            if (ThreadReceiver != null)
            {
                ThreadReceiver.Abort();
                ThreadReceiver = null;
            }
            if (ThreadHeart != null)
            {
                ThreadHeart.Abort();
                ThreadHeart = null;
            }

            Thread.Sleep(ChonglianTimeOut);

            Start(ServerIP, ServerProt);
        }

        void ClientSender()
        {
            while (true)
            {
                byte[] stream = null;
                lock (ListMessage)
                {
                    if (ListMessage.Count > 0)
                    {
                        stream = ListMessage[0];
                        ListMessage.RemoveAt(0);
                    }
                }
                if (stream != null)
                {
                    try
                    {
                        ClientSocket.Send(stream);
                    }
                    catch (Exception ex)
                    {
                        //Send_Erro(ex.Message);
                        goto End;
                    }
                }
                else
                {
                    Thread.Sleep(100);
                }
            }

            End:
            new Thread(Stop).Start();
        }

        void SendHeart()
        {
            while (true)
            {
                //避免初始化未获取到服务端分配ID的尴尬
                Thread.Sleep(10000);

                Send(ClientID, DataType.Base, MessType.Heart);
            }
        }

    }
}
